package com.bubbo.rpc.client;

import com.bubbo.rpc.client.bean.RpcRequest;
import com.bubbo.rpc.client.bean.RpcResponse;
import com.bubbo.rpc.client.util.Decoder;
import com.bubbo.rpc.client.util.Encoder;
import com.bubbo.rpc.client.util.serialize.Serializer;
import com.bubbo.rpc.client.util.serialize.impl.ProtostuffSerializer;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by waasdasd on 2017/3/31.
 */
public class BubboClient extends SimpleChannelInboundHandler<RpcResponse> {
    private static Logger logger = LoggerFactory.getLogger(BubboClient.class);

    public BubboClient(int port, String host) {
        this.port = port;
        this.host = host;
        this.serializer = new ProtostuffSerializer();
    }
    public BubboClient(int port, String host,Serializer serializer) {
        this.port = port;
        this.host = host;
        this.serializer = serializer;
    }


    private Serializer serializer;
    private String host;
    private int port;

    private RpcResponse rpcResponse;


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcResponse msg) throws Exception {
        this.rpcResponse = msg;
    }

    public RpcResponse send(RpcRequest request) throws Exception {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel channel) throws Exception {
                    ChannelPipeline pipeline = channel.pipeline();
                    pipeline.addLast(new Encoder(RpcRequest.class,serializer)); // 编码 RPC 请求
                    pipeline.addLast(new Decoder(RpcResponse.class,serializer)); // 解码 RPC 响应
                    pipeline.addLast(BubboClient.this); // 处理 RPC 响应
                }
            });
            bootstrap.option(ChannelOption.TCP_NODELAY, true);
            // 连接 RPC 服务器
            ChannelFuture future = bootstrap.connect(host, port).sync();
            // 写入 RPC 请求数据并关闭连接
            Channel channel = future.channel();
            channel.writeAndFlush(request).sync();
            channel.closeFuture().sync();
            // 返回 RPC 响应对象
            return rpcResponse;
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return rpcResponse;
        }
        finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}
